package com.xuecheng.orders.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.base.utils.IdWorkerUtils;
import com.xuecheng.base.utils.QRCodeUtil;
import com.xuecheng.messagesdk.model.po.MqMessage;
import com.xuecheng.messagesdk.service.MqMessageService;
import com.xuecheng.orders.config.AlipayConfig;
import com.xuecheng.orders.config.PayNotifyConfig;
import com.xuecheng.orders.mapper.XcOrdersGoodsMapper;
import com.xuecheng.orders.mapper.XcOrdersMapper;
import com.xuecheng.orders.mapper.XcPayRecordMapper;
import com.xuecheng.orders.model.dto.AddOrderDto;
import com.xuecheng.orders.model.dto.PayRecordDto;
import com.xuecheng.orders.model.dto.PayStatusDto;
import com.xuecheng.orders.model.po.XcOrders;
import com.xuecheng.orders.model.po.XcOrdersGoods;
import com.xuecheng.orders.model.po.XcPayRecord;
import com.xuecheng.orders.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageBuilderSupport;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${pay.url}")
    private String url;


    @Autowired
    private XcOrdersGoodsMapper xcOrdersGoodsMapper;


    @Autowired
    private XcOrdersMapper xcOrdersMapper;

    @Autowired
    private XcPayRecordMapper xcPayRecordMapper;

    @Autowired
    private MqMessageService mqMessageService;


    @Value("${pay.alipay.Id}")
    String APP_ID;
    @Value("${pay.alipay.priverAppKey}")
    String APP_PRIVATE_KEY;

    @Value("${pay.alipay.publicAppKey}")
    String APP_PUBLIC_KEY;

/*保存支付记录
* */
    public XcPayRecord createPayRecord(XcOrders orders){

        //订单id
        Long id = orders.getId();
        XcOrders xcOrders = xcOrdersMapper.selectById(id);
        if (xcOrders==null){

                XueChengPlusException.cast("订单不存在");
        }
        //订单状态
        String status = xcOrders.getStatus();
        //如果订单为成功,不在添加记录
        if ("601002".equals(status)){

            XueChengPlusException.cast("此订单已经支付");
        }
        XcPayRecord xcPayRecord = new XcPayRecord();
        xcPayRecord.setPayNo(IdWorkerUtils.getInstance().nextId());//支付记录号 ，将来传给支付宝
        xcPayRecord.setOrderId(id);
        xcPayRecord.setOrderName(xcOrders.getOrderName());
        xcPayRecord.setTotalPrice(xcOrders.getTotalPrice());
        xcPayRecord.setCurrency("CNY");
        xcPayRecord.setCreateDate(LocalDateTime.now());
        xcPayRecord.setStatus("601001"); //没有支付
        xcPayRecord.setUserId(xcOrders.getUserId());
        int insert = xcPayRecordMapper.insert(xcPayRecord);
        if (insert<=0){
            XueChengPlusException.cast("插入记录失败");
        }

        return xcPayRecord;



    }


    @Transactional
    @Override
    public PayRecordDto createOrder(String userId, AddOrderDto addOrderDto)  {


        //插入订单
        XcOrders xcOrders = saveXcOrders(userId, addOrderDto);

        //插入支付记录
        XcPayRecord payRecord = createPayRecord(xcOrders);

        //生成二维码
        QRCodeUtil qrCodeUtil = new QRCodeUtil();
        //配置二维码的url
        String format = String.format(url, payRecord.getPayNo());
        String qrCode=null;
        try {
            //二维码图片
            qrCode = qrCodeUtil.createQRCode(format, 200, 200);
        } catch (IOException e) {
            XueChengPlusException.cast("生成二维码出错");
        }
        PayRecordDto payRecordDto = new PayRecordDto();
        BeanUtils.copyProperties(payRecord,payRecordDto);
        payRecordDto.setQrcode(qrCode);



        return payRecordDto;
    }

    @Override
    public XcPayRecord getPayRecordByPayno(String payNo) {


        return      xcPayRecordMapper.selectOne(new LambdaQueryWrapper<XcPayRecord>().eq(XcPayRecord::getPayNo,payNo));
    }

    @Override
    public PayRecordDto queryPayResult(String payNo) {
            //查询支付结果
        PayStatusDto payStatusDto = queryPayResultFromAlipay(payNo);
        System.out.println(payStatusDto);
        //拿到支付结果记录表和订单表的状态
        saveAliPayStatus(payStatusDto);
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNo);
        PayRecordDto payRecordDto = new PayRecordDto();
        BeanUtils.copyProperties(payRecordByPayno,payRecordDto);



        return payRecordDto;
    }

    /*
    * 保存订单信息
    * */
    @Transactional
    public XcOrders saveXcOrders(String userId, AddOrderDto addOrderDto) {
        XcOrders orderByBusinessId = getOrderByBusinessId(addOrderDto.getOutBusinessId());
        if (orderByBusinessId!=null){
            return orderByBusinessId;
        }


        //插入订单的主表
        XcOrders xcOrders = new XcOrders();
        //使用雪花算法生成id
        xcOrders.setId(IdWorkerUtils.getInstance().nextId());
        xcOrders.setTotalPrice(addOrderDto.getTotalPrice());
        xcOrders.setCreateDate(LocalDateTime.now());
        xcOrders.setStatus("60001");//未支付
        xcOrders.setUserId(userId);
        xcOrders.setOrderType("60201");//订单类型
        xcOrders.setOrderName(addOrderDto.getOrderName());
        xcOrders.setOrderDescrip(addOrderDto.getOrderDescrip());
        xcOrders.setOrderDetail(addOrderDto.getOrderDetail());
        xcOrders.setOutBusinessId(addOrderDto.getOutBusinessId());//如果选课就记录了选课表的id
        int insert = xcOrdersMapper.insert(xcOrders);
        if (insert<0){
            XueChengPlusException.cast("添加订单失败");
        }
        //订单id
        Long id = xcOrders.getId();

        //插入订单的明细
        //将前端传入的JSON明细信息装成List
        String orderDescripJson = addOrderDto.getOrderDescrip();
        List<XcOrdersGoods> xcOrdersGoodsList = JSON.parseArray(orderDescripJson, XcOrdersGoods.class);
        xcOrdersGoodsList.forEach(gooo->{
            gooo.setOrderId(id);
            int insert1 = xcOrdersGoodsMapper.insert(gooo);

        });
        return xcOrders;
    }

    //根据业务id查询订单
    public XcOrders getOrderByBusinessId(String businessId) {
        XcOrders orders = xcOrdersMapper.selectOne(new LambdaQueryWrapper<XcOrders>().eq(XcOrders::getOutBusinessId, businessId));
        return orders;
    }


    /*请求支付宝的查询结果
    * */
    public PayStatusDto queryPayResultFromAlipay(String payNo){
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, APP_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no",payNo);
        request.setBizContent(jsonObject.toString());
        String body=null;
        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (!response.isSuccess()){//交易不成功
                XueChengPlusException.cast("请求支付宝查询支付失败");

            }
            body = response.getBody();
        } catch (AlipayApiException e) {
            XueChengPlusException.cast("请求支付宝查询支付失败");
        }
        Map<String,String> map = JSON.parseObject(body, Map.class);

        //解析支付结果
        PayStatusDto payStatusDto = new PayStatusDto();
        payStatusDto.setOut_trade_no(payNo);
        payStatusDto.setTrade_no(map.get("trade_no"));//交易号
        payStatusDto.setTrade_status(map.get("trade_status"));//交易状态
        payStatusDto.setApp_id(APP_ID);
        payStatusDto.setTotal_amount(map.get("total_amount"));


        System.out.println(body);

        return payStatusDto;


    }
    /*保存支付结果
    * */
    @Override
    @Transactional
    public void saveAliPayStatus(PayStatusDto payStatusDto){
        String payNO = payStatusDto.getOut_trade_no();
        XcPayRecord payRecordByPayno = getPayRecordByPayno(payNO);
        if (payRecordByPayno==null){
            XueChengPlusException.cast("找不到相关的支付记录号");
        }
        //拿到订单id
        Long orderId = payRecordByPayno.getOrderId();
        XcOrders xcOrders = xcOrdersMapper.selectById(orderId);
        if (xcOrders == null) {
            XueChengPlusException.cast("找不到相关联的订单号");

        }

        //支付状态
        String status = payRecordByPayno.getStatus();
        if ("601002".equals(status)){
        return;
        }
        //如果支付成功
        String trade_status = payStatusDto.getTrade_status();
        if (trade_status.equals("TRADE_SUCCESS")){//支付宝返回的结果为支付成功
            //更新支付记录表的状态为支付成功
            payRecordByPayno.setStatus("601002");
            //支付宝的订单号
            payRecordByPayno.setOutPayNo(payStatusDto.getTrade_no());
            // 第三方的渠道编号
            payRecordByPayno.setOutPayChannel("Alipay");
            //支付成功时间
            payRecordByPayno.setPaySuccessTime(LocalDateTime.now());
            xcPayRecordMapper.updateById(payRecordByPayno);
            //更新订单表的状态为成功
            xcOrders.setStatus("60002");//订单状态为成功
            xcOrdersMapper.updateById(xcOrders);
            //将消息写进数据库
            MqMessage payresult_notify = mqMessageService.addMessage("payresult_notify", xcOrders.getOutBusinessId(), xcOrders.getOrderType(), null);
            //发送消息
            notifyPayResult(payresult_notify );


        }


    }

    @Override
    public void notifyPayResult(MqMessage message) {
        Long id = message.getId();

        //消息内容
        String JsonString = JSON.toJSONString(message);

        //创建一个消息的持久化
        MessageBuilderSupport<Message> messageMessageBuilderSupport = MessageBuilder.withBody(JsonString.getBytes(StandardCharsets.UTF_8)).setDeliveryMode(MessageDeliveryMode.PERSISTENT);




        CorrelationData correlationData = new CorrelationData();
        correlationData.getFuture().addCallback(rest->{
            if (rest.isAck()){
            //消息发送成功
                log.debug("发送消息成功"+JsonString);
                //将消息从数据表删除
                mqMessageService.completed(id);
            }else {
            //消息发送失败
                log.debug("发送消息失败");
            }

        },ex->{
            //出现异常
        });

        rabbitTemplate.convertAndSend( PayNotifyConfig.PAYNOTIFY_EXCHANGE_FANOUT,"",message,correlationData);

    }
}

